package com.zyb.beiojcodesandbox.controller;

import cn.hutool.crypto.digest.DigestUtil;
import com.zyb.beiojcodesandbox.model.ExecuteCodeRequest;
import com.zyb.beiojcodesandbox.model.ExecuteCodeResponse;
import com.zyb.beiojcodesandbox.model.User;
import com.zyb.beiojcodesandbox.service.JavaDockerCodeSandbox;
import com.zyb.beiojcodesandbox.service.JavaNativeCodeSandbox;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.HashSet;

@RestController
@Slf4j
public class CodeSandboxController {

    //代码沙箱的Docker实现
    @Resource
    private JavaDockerCodeSandbox javaDockerCodeSandbox;

    //代码沙箱的原生实现（命令行）
    @Resource
    private JavaNativeCodeSandbox javaNativeCodeSandbox;

    private static HashSet<String> nonceStorage = new HashSet<>(1024);

    @Resource
    private RestTemplate restTemplatere;


    @PostMapping("/executeCode")
    ExecuteCodeResponse executeCode(@RequestBody ExecuteCodeRequest executeCodeRequest, HttpServletRequest request){
        if (executeCodeRequest == null) {
            throw new RuntimeException("请求参数为空");
        }
        //#######开始进行API认证逻辑##########
        //拿到请求头中需要用到的参数
        log.info("开始进行API验证");
        String accessKey = request.getHeader("accessKey");
        String sign = request.getHeader("sign");
        String nonce = request.getHeader("nonce");
        String timestamp = request.getHeader("timestamp");
        String body = request.getHeader("body");
        //对传输过来的参数进行校验
        if (nonceStorage.contains(nonce)) throw new RuntimeException("你无权限调用本服务");
        // 获取当前时间戳（毫秒）
        BigInteger timestampNow = new BigInteger(String.valueOf(System.currentTimeMillis()));
        BigInteger timestampOld = new BigInteger(timestamp);
        long l = timestampNow.subtract(timestampOld).longValue();
        if (l > 1000 * 10) throw new RuntimeException("你无权限调用本服务");

        //将参数放入到一个hashmap中
        HashMap<String, String> signProvider = new HashMap<>();

        signProvider.put("accessKey",accessKey);
        signProvider.put("nonce",nonce);
        signProvider.put("timestamp",timestamp);
        signProvider.put("body",body);

        //通过请求用户服务拿到sk
        HashMap<String, String> param = new HashMap<>();
        param.put("accessKey",accessKey);
        User user = restTemplatere.getForObject("http://beioj-backend-user-service/api/user/inner/get/ak?accessKey={accessKey}", User.class, param);
        String secretKey = user.getSecretKey();
        //进行sha256加密
        String checkKey = DigestUtil.sha256Hex(signProvider.toString() + "." + secretKey);

        System.out.println("服务方加密串：" + signProvider.toString() + "." + secretKey);
        if (!checkKey.equals(sign)) throw new RuntimeException("你无权限调用本服务");
        nonceStorage.add(nonce);
        if (nonceStorage.size() == 1024) nonceStorage = new HashSet<>(1024);
        //#######开始进行代码沙箱工作逻辑##########
        //这里我们使用docker的代码实现
        log.info("API验证通过");
        return javaDockerCodeSandbox.executeCode(executeCodeRequest);
    }
}
